package com.mybatis.jpa.interceptor;

import com.mybatis.jpa.constants.EnumAction;
import com.mybatis.jpa.executor.Executor;
import com.mybatis.jpa.executor.ExecutorFactory;
import com.mybatis.jpa.utils.MappedStatementUtils;
import com.mybatis.jpa.utils.MetaObjectUtils;
import com.mybatis.jpa.utils.StopWatchExt;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.util.Properties;

/**
 * mybatis拦截器<br>
 * 通过拦截<code>StatementHandler</code>的<code>prepare</code>
 * 方法，根据参数parameterObject配置的注解信息，自动生成sql语句。
 * 签名里要拦截的类型只能是接口。
 * @author K
 *
 */
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class JpaInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger( JpaInterceptor.class);

    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //MetaObject是Mybatis提供的一个的工具类,用于获取属性的值（支持OGNL的方法）
        MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
        metaStatementHandler = MetaObjectUtils.getOriginalMetaObject(metaStatementHandler);
        //获取mapper文件的sql语句
        String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");

        MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
        String method = MappedStatementUtils.getClassMethod(mappedStatement);

        if (StringUtils.isNotBlank(originalSql)) {
            return invocation.proceed();
        }

        StopWatchExt stopWatchExt = new StopWatchExt();
        if (method.equalsIgnoreCase(EnumAction.getValue(method))) {
            Executor execute = ExecutorFactory.getInstance(method);
            execute.process(metaStatementHandler);
        } else if (StringUtils.startsWith(method, EnumAction.QUERY.getKey())) {
            Executor execute = ExecutorFactory.getInstance(EnumAction.QUERY.getKey());
            execute.process(metaStatementHandler);
        }
        logger.info("拦截器执行耗时：{}", stopWatchExt.getTimeWithReset(true));

        // 传递给下一个拦截器处理
        return invocation.proceed();
    }

    public Object plugin(Object target) {
        if (target == null) {
            return target;
        }
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties properties) {

    }
}
